package com.dong.config;

import com.dong.annotation.ExceptionMessageAnnotation;
import com.dong.utils.WechatMessageUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URISyntaxException;

/**
 * @author DongJian
 * @date Created in 2020/10/22 14:43
 * Utils: Intellij Idea
 * @description:
 * @version:1.0
 */
@Slf4j
@Aspect
@Component
public class AopConfig {

    @Autowired
    WechatMessageUtil wechatMessageUtil;

    /**
     * 定义一个切点
     **/
    @Pointcut(value = "@annotation(com.dong.annotation.ExceptionMessageAnnotation)")
    public void cutOffPoint() {

    }

    /**
     * 前置通知
     **/
    @Before("cutOffPoint()")
    public void before() {
        System.out.println("前置通知，在切点前执行");
    }

    /**
     * 后置通知
     **/
    @After("cutOffPoint()")
    public void after() {
        System.out.println("后置通知，在切点后执行");
    }

    ThreadLocal<Long> timeThreadLocal = new ThreadLocal<>();

    /**
     * 环绕执行的应用场景
     * 1.全局异常处理
     * 2.日志操作
     * 3.全局的事务处理
     * 4.数据的全局缓存
     **/
    @Around("cutOffPoint()")
    public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws IOException, URISyntaxException {
        timeThreadLocal.set(System.currentTimeMillis());
        Object obj = null;
        Object[] args = proceedingJoinPoint.getArgs();

        try {
            // 必须要执行proceed方法，用于启动目标方法的执行，若不执行则目标方法也不会执行
            obj = proceedingJoinPoint.proceed(args);
            // 执行记录
            log.info("{} 方法执行时间为：{}", proceedingJoinPoint.getSignature().getName(), (System.currentTimeMillis() - timeThreadLocal.get()));
        } catch (Throwable throwable) {
            try {
                // 企业微信通知 todo 可扩展:提供多种方式的消息推送 1.邮件 2.钉钉
                Method method = ((MethodSignature) proceedingJoinPoint.getSignature()).getMethod();
                boolean hasAnnotation = method.isAnnotationPresent(ExceptionMessageAnnotation.class);
                if (hasAnnotation) {
                    final ExceptionMessageAnnotation annotation = method.getAnnotation(ExceptionMessageAnnotation.class);
                    wechatMessageUtil.sendMarkDownMessage(annotation.robotkey(), "template/markdown_template.md", annotation, throwable.getMessage());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            obj = throwable.toString();
        }
        return obj;
    }


    /**
     * @Description 切入点返回执行结果之后执行
     * 可以用于支付完成后对参数的二次校验，防止在方法执行时参数被修改
     **/
/*    @AfterReturning(returning = "result", pointcut = "cutOffPoint()")
    public void doAfterReturning(Object result) {
        // 制造错误
        log.info("大家好，我是xx,他们都秀完了，该我上场了！");
        if (Objects.isNull(result)) {
            result = "success1";
        }
    }*/

    /**
     * 切入执行报错的时候执行
     **/
    @AfterThrowing(throwing = "e", pointcut = "cutOffPoint()")
    public void doAfterThrowing(Throwable e) {
        log.error("错误信息：{}", e.getMessage());
    }
}
